package com.ywwxhz.app;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 自定义的 异常处理类 , 实现了 UncaughtExceptionHandler接口
 *
 * @author Administrator
 */
public class MyCrashHandler implements UncaughtExceptionHandler {
    // 需求是 整个应用程序 只有一个 MyCrash-Handler
    private static MyCrashHandler myCrashHandler;
    private Context context;
    private SimpleDateFormat dataFormat = new SimpleDateFormat(
            "yyyy_MM_dd_HH_mm_ss", Locale.CHINA);

    // 1.私有化构造方法
    private MyCrashHandler() {

    }

    public static synchronized MyCrashHandler getInstance() {
        if (myCrashHandler != null) {
            return myCrashHandler;
        } else {
            myCrashHandler = new MyCrashHandler();
            return myCrashHandler;
        }
    }

    public void init(Context context) {
        this.context = context;
    }

    public void uncaughtException(Thread arg0, Throwable arg1) {
        // 1.获取当前程序的版本号. 版本的id
        String versioninfo = getVersionInfo();

        // 2.获取手机的硬件信息.
        String mobileInfo = getMobileInfo();

        // 3.把错误的堆栈信息 获取出来
        String errorinfo = getErrorInfo(arg0, arg1);

        // 4.把所有的信息 还有信息对应的时间 提交到服务器
        try {
            if (Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)) {
                File f = context.getExternalCacheDir();// 获取SD卡目录
                File fileDir = new File(f, "crashlog_"
                        + dataFormat.format(new Date()) + ".txt");
                FileOutputStream os = new FileOutputStream(fileDir);
                os.write(new String(versioninfo + mobileInfo + errorinfo)
                        .getBytes());
                os.close();
                Toast.makeText(context,
                        "任务管理已崩溃，崩溃日志路径：" + fileDir.getAbsolutePath(),
                        Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(-1);
    }

    /**
     * 获取错误的信息
     *
     * @param arg1
     * @return
     */
    private String getErrorInfo(Thread arg0, Throwable arg1) {
        StringBuffer sb = new StringBuffer();
        // 通过反射获取系统的硬件信息
        sb.append("=====================Thread Info=========================\n");
        try {
            Field[] fields = arg0.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 暴力反射 ,获取私有的信息
                field.setAccessible(true);
                String name = field.getName();
                String value = field.get(null).toString();
                sb.append(name + "=" + value);
                sb.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        sb.append("=====================Tracert Info=========================\n");
        Writer writer = new StringWriter();
        PrintWriter pw = new PrintWriter(writer);
        arg1.printStackTrace(pw);
        pw.close();
        sb.append(writer.toString());
        return sb.toString();
    }

    /**
     * 获取手机的硬件信息
     *
     * @return
     */
    private String getMobileInfo() {
        StringBuffer sb = new StringBuffer();
        // 通过反射获取系统的硬件信息
        sb.append("=====================Hardware Info=========================\n");
        try {

            Field[] fields = Build.class.getDeclaredFields();
            for (Field field : fields) {
                // 暴力反射 ,获取私有的信息
                field.setAccessible(true);
                String name = field.getName();
                String value = field.get(null).toString();
                sb.append(name + "=" + value);
                sb.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 获取手机的版本信息
     *
     * @return
     */
    private String getVersionInfo() {
        try {
            StringBuffer sb = new StringBuffer();
            sb.append("=====================Software Info=========================\n");
            PackageManager pm = context.getPackageManager();
            PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
            sb.append("vierion=");
            sb.append(info.versionCode);
            sb.append("\n");
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "版本号未知";
        }
    }
}